#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
Created on 18/03/2010

@author: sebas
'''
from service import Resolver
import cmd
import difflib

from model import Item

class UpdateBookMenu(cmd.Cmd):
  BOOKNAME_PROMPT = "Book Name"
  NAME_PROMPT = "Name"
  SORTNAME_PROMPT = "Sortname"

  class State(object):
    CONTINUE = "___CONTINUE"
    ABORT = "___ABORT"
    
    def __init__(self, item, db):
      self.item = item
      self.action = self.CONTINUE
      self.db = db

  def __init__(self, state):
    cmd.Cmd.__init__(self)
    self.state = state
    self.doc_header = "Ayuda"
    self.ruler = "-"
    self.resolver = Resolver()
    self.current = 0
    self.__to_delete = set()
    self.authors = set()     
    for i in self.state.db:
      if i.get_attribute(Item.EDITED):
        self.authors.update(i.bookfile.book.authors)
 
    self.intro = self.__header()
    self.__set_bookname_request()

  def do_open(self, args):
    self.resolver.open(self.state.item.bookfile.location)

  def do_exit(self, args):
    self.state.action = UpdateBookMenu.State.ABORT
    return self.state

  def emptyline(self):
    if self.__requesting_bookname():
      return self.default(self.state.item.bookfile.book.title)
    elif self.__requesting_name():
      return self.default(self.__current().name)
    elif self.__requesting_sortname():
      return self.default(self.__current().sortname)

  def do_d(self, args):
    return self.do_delete(args)

  def do_delete(self, args):
    if not self.__requesting_bookname():
      if len(self.state.item.bookfile.book.authors) == 1:
        print "Hay un único autor, no se puede eliminar"
      else:
        self.__to_delete.add(self.__current())
        return self.__end()

  def do_set(self, args):
    if self.__requesting_name():
      try:
        idx = int(args)
        alternatives = difflib.get_close_matches(self.__current().name, map(lambda x: x.name, self.authors))
        match = filter(lambda a : a.name == alternatives[idx], self.authors)[0]
        self.__current().name = match.name
        self.__current().sortname = match.sortname
        return self.__end()
      except ValueError:
        print "%s no es un numero, reintente" % args
    
  def default(self, line):
    if self.__requesting_bookname():
      if line:
        self.state.item.bookfile.book.title = line
      self.__set_name_request()
    elif self.__requesting_name():
      if self.__current().name != line:
        self.__current().sortname = self.resolver.sortname_from_name(line)
      self.__current().name = line
      self.__set_sortname_request()
    elif self.__requesting_sortname():
      if line:
        self.__current().sortname = line
      self.authors.add(self.__current())
      return self.__end()

  def __set_bookname_request(self):
    self.prompt = "%s (%s)> " % (self.BOOKNAME_PROMPT, self.state.item.bookfile.book.title)
    
  def __set_name_request(self):
    authors = map(lambda x: x.name, self.authors)
    alternatives = difflib.get_close_matches(self.__current().name, authors)
    if len(alternatives) > 0:
      print "Autores similares:"
      for i, a in enumerate(alternatives):
        print "\t%d. %s" % (i, a)
    self.prompt = "%s (%s)> " % (self.NAME_PROMPT, self.__current().name)

  def __set_sortname_request(self):
    self.prompt = "%s (%s)> " % (self.SORTNAME_PROMPT, self.__current().sortname)

  def __requesting_bookname(self):
    return self.prompt.startswith(self.BOOKNAME_PROMPT)

  def __requesting_name(self):
    return self.prompt.startswith(self.NAME_PROMPT)

  def __requesting_sortname(self):
    return self.prompt.startswith(self.SORTNAME_PROMPT)

  def __current(self):
    return self.state.item.bookfile.book.authors[self.current]

  def __next_author(self):
    self.current += 1

  def __end(self):
    self.__next_author()
    if len(self.state.item.bookfile.book.authors) == self.current:
      authors = self.state.item.bookfile.book.authors 
      for a in self.__to_delete:
        del authors[authors.index(a)]
      return self.state
    self.__set_name_request()
    return None
  
  def __header(self):
    return """---------------------------------------------
Libro: %s
Autores: %s
Archivo: %s
Info de google: %s
---------------------------------------------""" % (self.state.item.bookfile.book.title,
                                                    map(lambda x : "%s (%s)" % (x.name, x.sortname), self.state.item.bookfile.book.authors),
                                                    self.state.item.bookfile.location,
                                                    ("Si" if self.state.item.bookfile.book.gbook is not None else "No"))
    
class MainMenu(cmd.Cmd):
  def __init__(self, normalizer):
    cmd.Cmd.__init__(self)
    self.normalizer = normalizer
    self.prompt = "> "
    self.doc_header = "Ayuda"
    self.ruler = "-"
    self.intro = "Bienvenido a eBookNormalizer, tipear '?' para ayuda"
  
  def do_collect(self, args):
    '''
      Explora el directorio origen infiriendo datos
    '''
    self.normalizer.collect_info()
  
  def do_clear_attributes(self, args):
    resp = raw_input("Realmente desea limpiar todos los atributos? (Si/NO) ")
    if resp == "Si":
      self.normalizer.clear_attributes()

  def do_process(self, args):
    self.normalizer.process()

  def do_remains_books(self, args):
    self.normalizer.remains_books()

  def do_processed_books(self, args):
    self.normalizer.processed_books()

  def do_remains_authors(self, args):
    self.normalizer.remains_authors()

  def do_processed_authors(self, args):
    self.normalizer.processed_authors()

  def do_convert(self, args):
    self.normalizer.convert()

  def do_update(self, args):
    '''
      Actualiza la base con los nuevos cambios, en breve vuela...
    '''
    try:
      if args is not None and len(args) > 0:
        idx = int(args.strip())
      else:
        idx = None
      self.normalizer.update(idx)
    except ValueError:
      print "%s no es un valor entero, imposible procesar el argumento" % args

  def do_authors(self, args):
    '''
      Muestra la información de autores recolectada y procesada
    '''
    self.normalizer.authors()

  def do_books(self, args):
    '''
      Muestra la información de libros recolectada y procesada
    '''
    self.normalizer.books()

  def do_detail(self, args):
    '''
      Muestra información detallada de un libro de la base
    '''
    self.normalizer.detail(int(args))
      
  def do_exit(self, args):
    '''
      salir del programa
    '''
    return 1
  
  def do_EOF(self, args):
    '''
      salir del programa
    '''
    print
    return 1

  def do_help(self, args):
    '''
      la ayuda que esta viendo
    '''
    cmd.Cmd.do_help(self, args)

  def emptyline(self):
    return None
